package inventory.controller;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import inventory.common.CommonConstants;
import inventory.common.ResultData;
import inventory.entity.Equipment;
import inventory.entity.InRepositoryRecord;
import inventory.entity.MaterialStuff;
import inventory.entity.Terminal;
import inventory.entity.bo.MaterialBo;
import inventory.entity.bo.QueryThingsInRepositoryCondition;
import inventory.entity.po.EquipmentTerminalRepositoryPo;
import inventory.entity.po.InRepositoryRecordPo;
import inventory.entity.po.MaterialStuffRepositoryPo;
import inventory.service.EquipmentService;
import inventory.service.InRepositoryRecordService;
import inventory.service.RepositoryService;
import inventory.service.TerminalService;
import inventory.utils.MaterialInitUtil;
import inventory.utils.SelectingCondition;
import inventory.utils.SelectingMapGenerator;
import inventory.utils.UUIDUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Api(tags = {"入库记录", "出库记录"}, value = "出/入库记录相关接口")
@RestController
@RequestMapping(CommonConstants.MATERIAL_PREFIX)
public class InStorageController {


    @Autowired
    private InRepositoryRecordService inRepositoryRecordService;

    @Autowired
    private TerminalService terminalService;

    @Autowired
    private EquipmentService equipmentService;

    @Autowired
    private RepositoryService repositoryService;


    /**
     * 根据条件查询出入库记录（可变条件）
     *
     * @param condition
     * @return
     */
    @ApiOperation(value = "根据条件查询出入库记录（可变条件）")
    @RequestMapping(value = "/getInStorageRecordsByCondition", method = RequestMethod.POST)
    public ResultData getInStorageRecordsByCondition(SelectingCondition.MaterialCondition condition) {
        if (StringUtils.isEmpty(condition.getRoleId())) {
            return new ResultData().FAILD().setResultIns("需要roleId字段来查询出入库记录");
        }
        SelectingMapGenerator<InRepositoryRecordPo> mapGenerator = new SelectingMapGenerator<>(InRepositoryRecordPo.class, condition);
        Map resultQueryConditionMap = mapGenerator.getResultQueryConditionMap();
        if (resultQueryConditionMap.isEmpty()) {
            return new ResultData().FAILD().setResultIns("未检测到任何有效匹配条件");
        }
        List<InRepositoryRecordPo> inRepositoryRecordPos = inRepositoryRecordService.queryInRepositoryRecordPoByCondition(resultQueryConditionMap);
        return new ResultData().OK().setObjs(inRepositoryRecordPos);
    }

    /**
     * 查询所有出入库记录
     *
     * @return
     */
    @ApiOperation(value = "查询所有出入库记录")
    @RequestMapping(value = "/getAllInStorageRecordsOfRole", method = RequestMethod.GET)
    @ApiImplicitParam(name = "roleId", value = "登录用户对应的角色id")
    public ResultData getAllInStorageRecords(String roleId) {
        if (StringUtils.isEmpty(roleId)) {
            return new ResultData().FAILD().setResultIns("需要roleId字段来查询出入库记录");
        }
        List<InRepositoryRecordPo> inRepositoryRecordPos = inRepositoryRecordService.queryAllInRepositoryRecordPo(roleId);
        return new ResultData().OK().setObjs(inRepositoryRecordPos);
    }

    /**
     * 查询某一个时间段的出入库记录
     *
     * @return
     */
    @ApiOperation(value = "查询某一个时间段的出入库记录")
    @RequestMapping(value = "/getInStorageByTimePeriod", method = RequestMethod.GET)
    @ApiImplicitParams(
            {@ApiImplicitParam(name = "startTime", value = "开始时间点（格式：yyyy-MM-dd HH:mm:ss）"),
                    @ApiImplicitParam(name = "endTime", value = "结束时间点（格式：yyyy-MM-dd HH:mm:ss）")}
    )
    public ResultData getInStorageByTimePeriod(
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @RequestParam("startTime") Date startTime,
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @RequestParam("endTime") Date endTime) {
        List<InRepositoryRecordPo> inRepositoryRecordPos = inRepositoryRecordService.queryInRepositoryByTimePeriod(startTime, endTime);
        return new ResultData().OK().setObjs(inRepositoryRecordPos);
    }


    /**
     * 材料入库
     *
     * @param type
     * @param materialBo
     * @return
     */
    @RequiresPermissions("material:inStorage")
    @ApiOperation(value = "材料入库")
    @RequestMapping(value = "/inStorageMaterial/{type}", method = RequestMethod.POST)
    @ApiImplicitParam(name = "type", value = "入库材料类型，1:终端,2:设备,3:物料")
    public ResultData inStorageMaterial(@PathVariable("type")
                                                Integer type,
                                        @RequestBody MaterialBo materialBo) {
        //添加入库记录
        InRepositoryRecord inRepositoryRecord = MaterialInitUtil.initInRepositoryRecord(materialBo);
        if (type == 1) {//入库终端
//            System.out.println(materialBos);
            Date now = new Date();


            List<String> imeis = materialBo.getImei();
            for (String imei : imeis) {

                //录入终端信息
                Terminal terminal = new Terminal();
                terminal.setImei(imei);

                //判断是否已有imei，有则跳过
                if (terminalService.selectOne(new EntityWrapper<Terminal>().eq("IMEI", imei)) != null) {
                    continue;
                }

                terminal.setRepositoryId(materialBo.getTargetRepositoryId());
                terminal.setStatus(0);
                terminal.setTerminalId(UUIDUtils.getId());
                terminal.setTerminalTypicalId(materialBo.getMaterialTypicalId());
                terminal.setStorageTime(now);
                terminal.setTrace(terminal.getRepositoryId());


                inRepositoryRecord.setCount(inRepositoryRecord.getCount() + 1);
                boolean rs = inRepositoryRecordService.addTerminal(terminal, inRepositoryRecord);
                if (!rs) {
                    return new ResultData().FAILD().setResultIns("入库操作失败");
                }


            }


        } else if (type == 2) {//入库设备


            Date now = new Date();
//            //添加入库记录
//            InRepositoryRecord inRepositoryRecord = new InRepositoryRecord();
//            inRepositoryRecord.setCount(Long.valueOf(0));
//            inRepositoryRecord.setInRepositoryRecordId(UUIDUtils.getId());
//            inRepositoryRecord.setInTime(now);
//            inRepositoryRecord.setTypicalId(materialBo.getMaterialTypicalId());
//            inRepositoryRecord.setOperator(materialBo.getOperator());
//            inRepositoryRecord.setTargetRepository(materialBo.getTargetRepositoryId());

            List<String> imeis = materialBo.getImei();
            for (String imei : imeis) {


                //录入设备信息
                Equipment equipment = new Equipment();
                equipment.setImei(imei);

                //判断是否已有imei，有则跳过
                if (equipmentService.selectOne(new EntityWrapper<Equipment>().eq("IMEI", imei)) != null) {
                    continue;
                }

                equipment.setRepositoryId(materialBo.getTargetRepositoryId());
                equipment.setStatus(0);
                equipment.setEquipmentId(UUIDUtils.getId());
                equipment.setMaterialTypicalId(materialBo.getMaterialTypicalId());
                equipment.setStorageTime(now);
                equipment.setTrace(equipment.getRepositoryId());


                inRepositoryRecord.setCount(inRepositoryRecord.getCount() + 1);
                boolean rs = inRepositoryRecordService.addEquipment(equipment, inRepositoryRecord);
                if (!rs) {
                    return new ResultData().FAILD().setResultIns("入库操作失败");
                }

            }

        } else if (type == 3) {//入库物料

            Date now = new Date();

            //录入材料信息
            MaterialStuff materialStuff = MaterialInitUtil.initMaterialStuff(materialBo);

            //添加入库记录
//            InRepositoryRecord inRepositoryRecord = new InRepositoryRecord();
//            inRepositoryRecord.setCount(Long.valueOf(materialBo.getCount()));
//            inRepositoryRecord.setInRepositoryRecordId(UUIDUtils.getId());
//            inRepositoryRecord.setInTime(now);
//            inRepositoryRecord.setTypicalId(materialBo.getMaterialTypicalId());
//            inRepositoryRecord.setOperator(materialBo.getOperator());
//            inRepositoryRecord.setTargetRepository(materialBo.getTargetRepositoryId());


            boolean rs = inRepositoryRecordService.addStuff(materialStuff, inRepositoryRecord);
            if (!rs) {
                return new ResultData().FAILD().setResultIns("入库操作失败");
            }

        } else {
            return new ResultData().FAILD().setResultIns("无对应类型可以入库，请联系开发者");
        }
        return new ResultData().OK().setResultIns("入库成功");
    }


    //------------------------------------ttxxi start--------------------------------------------

    //    @RequiresPermissions("user:create")
    @RequiresPermissions("material:outStorage")
    @ApiOperation("材料出库(暂时废弃)")
    @RequestMapping(value = "/outStorageMaterial-1/{type}", method = RequestMethod.POST)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "出库材料类型，1:终端,2:设备,3:物料"),
//            @ApiImplicitParam(name = "materialBo",value = "type=1或2 时需要 materialTypicalId operator sourceRepositoryId targetRepositoryId imei;type=3时需要stuffId name count materialTypicalId operator sourceRepositoryId targetRepositoryId")
    })
    @Deprecated
    public ResultData outStorageMaterial(@PathVariable("type")
                                                 Integer type,
                                         @RequestBody MaterialBo materialBo, HttpServletRequest request) {

//        System.out.println("httpservlet的sessionId: "+request.getSession().getId());

        boolean res;

        //初始化出入库记录对象
        InRepositoryRecord inRepositoryRecord = MaterialInitUtil.initInRepositoryRecord(materialBo);

        if (type == 1) {//出库终端
            //materialPo用到了imei targetRepositoryId

            List<String> imeis = materialBo.getImei();

            res = inRepositoryRecordService.outTerminal(materialBo, inRepositoryRecord, imeis);


        } else if (type == 2) {//出库设备
            //materialPo用到了imei targetRepositoryId
            List<String> imeis = materialBo.getImei();

            res = inRepositoryRecordService.outEquipment(materialBo, inRepositoryRecord, imeis);

        } else if (type == 3) {//出库物料
            //materialPo用到了stuffId count targetRepository

            res = inRepositoryRecordService.outMaterialStuff(materialBo, inRepositoryRecord);

        } else {
            return new ResultData().FAILD().setResultIns("无对应类型可以入库，请联系开发者");
        }

        if (res) {
            return new ResultData().OK().setResultIns("出库成功");
        } else {
            return new ResultData().FAILD().setResultIns("出库失败，请检查参数是否正确");
        }


    }

    @RequiresPermissions("material:outStorage")
    @ApiOperation("材料出库")
    @RequestMapping(value = "/outStorageMaterial/{type}", method = RequestMethod.POST)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "出库材料类型，1:终端,2:设备,3:物料"),
    })
    public ResultData outStorageMaterial(@PathVariable("type") Integer type, @RequestBody MaterialBo materialBo) {


        //先构造条件，查询出对应仓库的对应目录对应类型的所有东西
        QueryThingsInRepositoryCondition queryThingsInRepositoryCondition = new QueryThingsInRepositoryCondition();
        queryThingsInRepositoryCondition.setCategoryId(type.toString());
        queryThingsInRepositoryCondition.setRepositoryId(materialBo.getSourceRepositoryId());
        queryThingsInRepositoryCondition.setTypicalId(materialBo.getMaterialTypicalId());

        if (materialBo.getCount() < 1) {
            return new ResultData().FAILD().setResultIns("出库失败，出库数量不能小于1");
        }

        List<String> imeis = new ArrayList<>();
        Map<String, Object> stuffMap = new HashMap<>();//存储符合要求的批次id，以及这个批次应该要出库的数量
        //针对同的类型去查询
        switch (type) {
            case 1:
            case 2:
                List<EquipmentTerminalRepositoryPo> equipmentTerminalRepositoryPoList = repositoryService.selectEquipmentTerminalInRepository(queryThingsInRepositoryCondition);
                //判断count数量是否大于数据库已有 的数量
                if (materialBo.getCount() > equipmentTerminalRepositoryPoList.size()) {
                    materialBo.setCount(equipmentTerminalRepositoryPoList.size());
                }

                for (int i = 0; i < materialBo.getCount(); i++) {
                    imeis.add(equipmentTerminalRepositoryPoList.get(i).getImei());
                }
                break;


            case 3:

                List<MaterialStuffRepositoryPo> materialStuffRepositoryPoList = repositoryService.selectMaterialStuffRepository(queryThingsInRepositoryCondition);
                Integer tempNum = 0;//记录累计各个批次的数量

                for (MaterialStuffRepositoryPo item : materialStuffRepositoryPoList) {

                    if (tempNum + item.getInRepository() >= materialBo.getCount()) {
                        stuffMap.put(item.getId(), materialBo.getCount() - tempNum);
                        break;
                    }
                    stuffMap.put(item.getId(), item.getInRepository());//把符合要求的批次id,以及数量加进去
                    tempNum += item.getInRepository();//增加临时变量的值
                }
                break;
            default:
                return new ResultData().FAILD().setResultIns("出库失败，请检查参数是否正确");
        }


        boolean res;

        //初始化出入库记录对象
        InRepositoryRecord inRepositoryRecord = MaterialInitUtil.initInRepositoryRecord(materialBo);

        if (type == 1) {//出库终端

            res = inRepositoryRecordService.outTerminal(materialBo, inRepositoryRecord, imeis);

        } else if (type == 2) {//出库设备

            res = inRepositoryRecordService.outEquipment(materialBo, inRepositoryRecord, imeis);

        } else if (type == 3) {//出库物料

            res = inRepositoryRecordService.outMaterialStuff(stuffMap, materialBo, inRepositoryRecord);

        } else {
            return new ResultData().FAILD().setResultIns("无对应类型可以入库，请联系开发者");
        }

        if (res) {
            return new ResultData().OK().setResultIns("出库成功");
        } else {
            return new ResultData().FAILD().setResultIns("出库失败，请检查参数是否正确");
        }


    }


    //------------------------------------ttxxi send--------------------------------------------


}
